package com.yanqu.road.server.manger.maidian;

import com.yanqu.road.dao.impl.maidian.LogClickHouseDao;
import com.yanqu.road.dao.impl.maidian.UserMaiDianLoginDataDaoImpl;
import com.yanqu.road.entity.log.maidian.LogUserBagChange;
import com.yanqu.road.entity.maidian.UserMaiDianLoginData;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.manger.DataAnalyticsMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserBagGoodsChangeMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(UserBagGoodsChangeMgr.class.getName());

    private static Map<Long, UserMaiDianLoginData> stateDataMap;

    private static boolean DRIVER_LOAD = false;

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        stateDataMap = new UserMaiDianLoginDataDaoImpl().getUserMaiDianStateData();
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {
        for (Map.Entry<Long, UserMaiDianLoginData> entry : stateDataMap.entrySet()) {
            UserMaiDianLoginData value = entry.getValue();
            if(value.isInsertOption()){
                new UserMaiDianLoginDataDaoImpl().add(value);
            }else if(value.isUpdateOption()){
                new UserMaiDianLoginDataDaoImpl().update(value);
            }
        }
        return true;
    }

    public static void addUserLoginTime(long userId){
        if(!DataAnalyticsMgr.openDataAnalytics()){
            return;
        }
        UserMaiDianLoginData userMaiDianStateData = stateDataMap.get(userId);
        if(userMaiDianStateData == null){
            synchronized (stateDataMap){
                userMaiDianStateData = stateDataMap.get(userId);
                if(userMaiDianStateData == null){
                    userMaiDianStateData = new UserMaiDianLoginData();
                    userMaiDianStateData.setUserId(userId);
                    userMaiDianStateData.setInsertOption();
                    stateDataMap.put(userId, userMaiDianStateData);
                }
            }
        }
        synchronized (userMaiDianStateData) {
            userMaiDianStateData.addLoginTime(DateHelper.getTodayZeroTime());
        }
    }

    public static void removeUserLoginTime(long userId, long time){
        UserMaiDianLoginData userMaiDianStateData = stateDataMap.get(userId);
        if(userMaiDianStateData != null){
            synchronized (userMaiDianStateData) {
                userMaiDianStateData.removeLoginTime(time);
            }
        }
    }

    /**
     * 上传前一天玩家背包变化
     */
    public static void traceLastDayUserBagChange() {

        if(!DataAnalyticsMgr.openDataAnalytics()){
            return;
        }

        if(!StringUtils.isNullOrEmpty(ChannelConfig.CLICKHOUSE_LOG_DB_CONNECT_URL)){
            if(!DRIVER_LOAD) {
                try {
                    Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
                    DRIVER_LOAD = true;
                } catch (ClassNotFoundException e) {
                    logger.error("", e);
                    return;
                }
            }
        }

        long yesterdayZeroTime = DateHelper.getTodayZeroTime() - (int)DateHelper.DAY_SECONDS;
        String date = DateHelper.getYMDBARString(yesterdayZeroTime * 1000);
        String endDate = DateHelper.getYMDBARString(yesterdayZeroTime * 1000 + DateHelper.DAY_MILLIONS);

        long yesterdayZero = yesterdayZeroTime * 1000;
        long todayZero = yesterdayZero + DateHelper.DAY_MILLIONS;

        int uploadNum = 0;
        for (Map.Entry<Long, UserMaiDianLoginData> entry : stateDataMap.entrySet()) {
            UserMaiDianLoginData userMaiDianStateData = entry.getValue();
            if(!userMaiDianStateData.getLoginTime().contains(yesterdayZeroTime)){
                continue;
            }
            //定时器，每5S上报5个玩家
            if(uploadNum >= 5){
                break;
            }
            uploadNum++;
            Long userId = entry.getKey();
            Map<Integer, List<LogUserBagChange>> dataListMap;
            if(StringUtils.isNullOrEmpty(ChannelConfig.CLICKHOUSE_LOG_DB_CONNECT_URL)){
                dataListMap = new UserMaiDianLoginDataDaoImpl().selectUserBagChange(userId, date);

                //元宝
                Map<Integer, List<LogUserBagChange>> ingotsChangeMap = new UserMaiDianLoginDataDaoImpl().selectUserIngotsChange(userId, date, endDate);
                for (Map.Entry<Integer, List<LogUserBagChange>> listEntry : ingotsChangeMap.entrySet()) {
                    if(!dataListMap.containsKey(listEntry.getKey())){
                        dataListMap.put(listEntry.getKey(), new ArrayList<>());
                    }
                    dataListMap.get(listEntry.getKey()).addAll(listEntry.getValue());
                }
            }else {
                //从ck获取
                dataListMap = new LogClickHouseDao().selectUserBagChange(ChannelConfig.CLICKHOUSE_LOG_DB_CONNECT_URL, userId, yesterdayZero, todayZero);

                //元宝
                Map<Integer, List<LogUserBagChange>> ingotsChangeMap = new LogClickHouseDao().selectUserIngotsChange(ChannelConfig.CLICKHOUSE_LOG_DB_CONNECT_URL, userId, yesterdayZero, todayZero);
                for (Map.Entry<Integer, List<LogUserBagChange>> listEntry : ingotsChangeMap.entrySet()) {
                    if(!dataListMap.containsKey(listEntry.getKey())){
                        dataListMap.put(listEntry.getKey(), new ArrayList<>());
                    }
                    dataListMap.get(listEntry.getKey()).addAll(listEntry.getValue());
                }

            }

            logger.info("start upload user {} bagChange ", userId);
            int count = 0;
            for (Map.Entry<Integer, List<LogUserBagChange>> listEntry : dataListMap.entrySet()) {
                List<LogUserBagChange> dataList = listEntry.getValue();

                //消耗或者获得
                int isGet = listEntry.getKey();

                if(dataList.size() > 0){

                    Map<Integer, List<LogUserBagChange>> wayMap = new HashMap<>();
                    for (LogUserBagChange bagChange : dataList) {

                        //途径
                        int way = bagChange.getWay();
                        if(!wayMap.containsKey(way)){
                            wayMap.put(way, new ArrayList<>());
                        }
                        wayMap.get(way).add(bagChange);
                    }

                    String eventName = isGet == 0 ? "resource_use" : "resource_get";

                    for (Map.Entry<Integer, List<LogUserBagChange>> e : wayMap.entrySet()) {

                        DefaultEventTraceAction action = newTraceAction(userId, eventName);
                        if(action == null){
                            break;
                        }
                        action.build("#time", DateHelper.getCurrentDateTimeString(yesterdayZeroTime * 1000));
                        //对象组长度上限
                        List<Map<String, Object>> groupList = new ArrayList<>();

                        int way = e.getKey();
                        List<LogUserBagChange> list = e.getValue();

                        //按途径上报！！！！！！
                        action.build("change_reason", way);

                        for (LogUserBagChange bagChange : list) {
                            count++;

                            Map<String, Object> map = new HashMap<>();
                            map.put("resource_id", bagChange.getGoodsId() == 0 ? GameConfig.GAME_MONEY_INGOTS : bagChange.getGoodsId());
                            map.put("change_num", bagChange.getTotal());
                            map.put("change_time", bagChange.getTimes());
                            groupList.add(map);

                            if(groupList.size() >= 500){
                                action.build("change_info", groupList);
                                action.trace();
                                action = newTraceAction(userId, eventName);
                                if(action == null){
                                    break;
                                }
                                action.build("#time", DateHelper.getCurrentDateTimeString(yesterdayZeroTime * 1000));
                                action.build("change_reason", way);
                                groupList = new ArrayList<>();
                            }
                        }

                        if(groupList.size() > 0 && action != null){
                            action.build("change_info", groupList);
                            action.trace();
                        }
                    }
                }
            }

            logger.info("end upload user {} bagChange, count {} ", userId, count);
            removeUserLoginTime(userId, yesterdayZeroTime);
        }
    }

    private static DefaultEventTraceAction newTraceAction(Long userId, String eventName) {
        DefaultEventTraceAction action;
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        if(gamePlayer != null){
            action = new DefaultEventTraceAction(eventName, gamePlayer);
        }else {
            UserInfo userInfo = UserMgr.getUserInfo(userId);
            if(userInfo == null){
                return null;
            }
            action = new DefaultEventTraceAction(eventName, userInfo);
        }
        return action;
    }
}
